home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
Drivers
/
Fd
/
Fd_reloc.tproj
/
Fd.m
< prev
next >
Wrap
Text File
|
1995-12-30
|
5KB
|
194 lines
/*
* THIS SOFTWARE IS PROVIDED BY MARK SALYZYN ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL MARK SALYZYN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @(#)Fd.m 1.1 (Salyzyn) 95/12/05
*/
#import "Fd.h"
/*
* A non-instantiated variable telling us which major number we are
* using. We do not allow more than one instance of the FD driver.
*/
static int FdMajor ;
@implementation Fd
#define Fdclose nulldev
+ (BOOL) probe : description
{ Fd * dev ;
IODirectDevice * desc ;
char Name[sizeof(FdDeviceName) + 1] ;
unsigned instance ;
const char * String ;
IOConfigTable * config = [description configTable] ;
const char * cp ;
static int Fdopen(), Fdclose(), Fdread(), Fdwrite(),
Fdioctl(), Fdselect() ;
extern nodev(), nulldev() ;
extern char * strcpy() ;
/*
* Find out what we have attached.
*/
if ((dev = [self alloc]) == nil) {
IOLog ("%s: Failed to allocate an instance\n", FdDeviceName) ;
return NO ;
}
strcpy (Name, FdDeviceName)[sizeof(Name) - 1] = '\0' ;
instance = 0 ;
if (String = [config valueForStringKey : "Instance"]) {
for (cp = String; ('0' <= *cp) && (*cp <= '9'); ++cp)
instance = (instance * 10) + *cp - '0' ;
[config freeString : String] ;
}
Name[sizeof(Name) - 2] = instance + '0' ;
[dev setName : Name] ;
[dev setDeviceKind : FdDeviceKind] ;
[dev setUnit : instance] ;
if (instance >= 1) {
[dev free] ;
IOLog ("%s Too many instances\n", [self name]) ;
return NO ;
}
if ((FdMajor = IOAddToCdevsw (
Fdopen, /* IOSwitchFunc openFunc */
Fdclose, /* IOSwitchFunc closeFunc */
Fdread, /* IOSwitchFunc readFunc */
Fdwrite, /* IOSwitchFunc writeFunc */
Fdioctl, /* IOSwitchFunc ioctlFunc */
nodev, /* IOSwitchFunc stopFunc */
nulldev, /* IOSwitchFunc resetFunc */
Fdselect, /* IOSwitchFunc selectFunc */
nodev, /* IOSwitchFunc mmapFunc */
nodev, /* IOSwitchFunc getcFunc */
nodev) /* IOSwitchFunc putcFunc */) == -1) {
[dev free] ;
IOLog ("%s failed to place into Cdevsw\n", [self name]) ;
return NO ;
}
[dev registerDevice] ;
if ((desc = [dev initFromDeviceDescription : description]) == nil) {
IOLog ("%s: Failed to init Device Description\n",FdDeviceName) ;
[dev free] ;
return NO ;
}
return YES ;
}
/*
* Name: getIntValues : values forParameter : parameter count : count
* Handle providing information back to user routines. This is an
* out-of-bound Kernel Server channel. We allow asking for the following:
* IOMajorDevice Major device of this instance of the driver
* IONumberDevice Number of ports handled on this instance.
*/
- (IOReturn) getIntValues : (unsigned *)values
forParameter : (IOParameterName) parameter
count : (unsigned *) count
{ unsigned maxCount = *count ;
if (maxCount == 0)
maxCount = IO_MAX_PARAMETER_ARRAY_LENGTH ;
if (strcmp(parameter, "IOMajorDevice") == 0) {
values[0] = FdMajor ;
*count = 1 ;
return IO_R_SUCCESS ;
}
if (strcmp (parameter, "IONumberDevice") == 0) {
values[0] = NOFILE ;
*count = 1 ;
return IO_R_SUCCESS ;
}
return [super getIntValues : values
forParameter : parameter
count : &maxCount] ;
}
/* ARGSUSED */
static int
Fdopen (dev_t dev, int flag, int mode)
{ struct file * fp ;
struct file * dfp ;
/*
* Find the file pointers for the file descriptors, both
* must be valid.
*/
if (((fp = getf (u.u_r.r_val1)) == NULL)
|| ((dfp = getf (minor (dev))) == NULL)
|| (fp == dfp))
return (EBADF) ;
/*
* Make sure opened up in same mode
*/
if (((flag & (FREAD | FWRITE)) | dfp->f_flag) != dfp->f_flag)
return (EACCES) ;
return (0) ;
}
static int
Fdread (dev_t dev, struct uio *uio, int flag)
{
if (u.u_ap[0] == minor (dev))
return (EBADF) ;
u.u_ap[0] = minor (dev) ;
/*
* Ok, so this is MACH specific, saves us some stack
* space though!
*/
rwuio (uio, UIO_READ) ;
return (u.u_error) ;
}
static int
Fdwrite (dev_t dev, struct uio *uio, int flag)
{
if (u.u_ap[0] == minor (dev))
return (EBADF) ;
u.u_ap[0] = minor (dev) ;
rwuio (uio, UIO_WRITE) ;
return (u.u_error) ;
}
static int
Fdioctl (dev_t dev, int cmd, caddr_t data, int flag)
{
if (u.u_ap[0] == minor (dev))
return (EBADF) ;
u.u_ap[0] = minor (dev) ;
ioctl () ;
return (u.u_error) ;
}
static int
Fdselect (dev_t dev, int rw)
{
struct file * fp ;
if (((fp = getf (minor(dev))) == NULL)
|| (fp->f_ops == NULL)
|| (fp->f_ops->fo_select == NULL))
return (1) ;
return ((*fp->f_ops->fo_select)(fp, rw)) ;
}
@end